subList返回的是原列表的一个视图,修改动作反映在原列表
Updated:
Contents
参考:《改善java程序的151个建议》
http://blog.csdn.net/chenssy/article/details/44102915
1 | public class Lian4 { |
分析:
- 先来看看源码:
1. public List<E> subList(int fromIndex, int toIndex) {
2. subListRangeCheck(fromIndex, toIndex, size);
3. return new SubList(this, 0, fromIndex, toIndex); //注意这个this,是原列表
4. }
5. /**
6. * 继承AbstractList类,实现RandomAccess接口
7. */
8. private class SubList extends AbstractList<E> implements RandomAccess {
9. private final AbstractList<E> parent; //列表
10. private final int parentOffset;
11. private final int offset;
12. int size;
13.
14. //构造函数
15. SubList(AbstractList<E> parent,
16. int offset, int fromIndex, int toIndex) {
17. this.parent = parent;
18. this.parentOffset = fromIndex;
19. this.offset = offset + fromIndex;
20. this.size = toIndex - fromIndex;
21. this.modCount = ArrayList.this.modCount;
22. }
23.
24. //set方法
25. public E set(int index, E e) {
26. rangeCheck(index);
27. checkForComodification();
28. E oldValue = ArrayList.this.elementData(offset + index);
29. ArrayList.this.elementData[offset + index] = e;
30. return oldValue;
31. }
32.
33. //get方法
34. public E get(int index) {
35. rangeCheck(index);
36. checkForComodification();
37. return ArrayList.this.elementData(offset + index);
38. }
39.
40. //add方法
41. public void add(int index, E e) {
42. rangeCheckForAdd(index);
43. checkForComodification();
44. parent.add(parentOffset + index, e);
45. this.modCount = parent.modCount;
46. this.size++;
47. }
48.
49. //remove方法
50. public E remove(int index) {
51. rangeCheck(index);
52. checkForComodification();
53. E result = parent.remove(parentOffset + index);
54. this.modCount = parent.modCount;
55. this.size--;
56. return result;
57. }
58. }
该SubLsit是ArrayList的内部类,它与ArrayList一样,都是继承AbstractList和实现RandomAccess接口。同时也提供了get、set、add、remove等list常用的方法。但是它的构造函数有点特殊,在该构造函数中有两个地方需要注意:
- 1、this.parent = parent;而parent就是在前面传递过来的list,也就是说this.parent就是原始list的引用。
2、this.offset = offset + fromIndex;this.parentOffset = fromIndex;。同时在构造函数中它甚至将modCount(fail-fast机制)传递过来了。
get、set、add、remove等都是在原列表上面做操作,它并没有像subString一样生成一个新的对象(subString返回的是新对象,因为String类时final的嘛。)。所以subList返回的只是原列表的一个视图,它所有的操作最终都会作用在原列表上。
再来看看c与c1为什么不相等,因为通过ArrayList构造函数创建的c1实际上是新列表,他是通过数组的copyOf动作生成的,所以生成的列表c1与原列表c之间没有关系(虽然是浅拷贝,但元素类型是String,也就相当于深拷贝了),c修改了与c1无关。